--[[
 -- *名称:AglorithmInterface
 -- *描述:前端调用接口
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-14
 -- *修改日期:2017-11-14
 ]]
local AglorithmInterface = pokercore.class();
local SuitAnalysisFactory = require(basePath.."suit/suitanalysisfactory");
local DdzCard = require(basePath .. "domain/ddzcard")
local StraightTypeAnalyzer = require(basePath.."suit/straight/straighttypeanalyzer"); --顺子
local SuperBombTypeAnalyzer = require(basePath.."suit/superbomb/superbombtypeanalyzer"); --超级炸弹
--local ThreeTypeAnalyzer = require(basePath.."suit/three/threetypeanalyzer"); --三条
--local ThreeStraightTypeAnalyzer = require(basePath.."suit/threestraight/threestraighttypeanalyzer"); --三顺
--local ThreeTakePairTypeAnalyzer = require(basePath.."suit/threetakepair/threetakepairtypeanalyzer"); --三带二
--local ThreeTakePairPlusTypeAnalyzer = require(basePath.."suit/threetakepairplus/threetakepairplustypeanalyzer"); --三带二翅膀
--local ThreeTakeSingleTypeAnalyzer = require(basePath.."suit/threetakesingle/threetakesingletypeanalyzer"); --三带一
--local ThreeTakeSinglePlusTypeAnalyzer = require(basePath.."suit/threetakesingleplus/threetakesingleplustypeanalyzer");  --三带一翅膀检测                  
local BombTypeAnalyzer =  require(basePath.."suit/bomb/bombtypeanalyzer");  --炸弹
--local FourTakePairTypeAnalyzer = require(basePath.."suit/fourtakepair/fourtakepairtypeanalyzer");  --四带二

local SingleAnalyzer = require(basePath .. "suit/single/singletypeanalyzer") ;
local PairAnalyzer  = require(basePath .. "suit/pair/pairtypeanalyzer") ;
local PairStraightAnalyzer = require(basePath .. "suit/pairstraight/pairstraighttypeanalyzer") ;
--local FourTakeSingleAnalyzer = require(basePath .. "suit/fourtakesingle/fourtakesingletypeanalyzer") ;
local SoftBombAnalyzer = require(basePath .. "suit/softbomb/softbombtypeanalyzer") ;
--local MissileAnalyzer= require(basePath .. "suit/missile/missiletypeanalyzer") ;

local outData = {
       [1] = {
            ["number"] = 1,
            ["laizi"] = 0,
            ["shape"] = 3,
            ["value"] = 14,
            ["laiziNumber"] = 0,
            ["laiziType"] = 0,
        },

    -- [2] = {
    --     ["number"] = 2,
    --     ["laizi"] = 0,
    --     ["shape"] = 3,
    --     ["value"] = 15,
    --     ["laiziNumber"] = 0,
    --     ["laiziType"] = 0,
    -- },
    -- [2] = {
    --     ["number"] = 6,
    --     ["shape"] = 0,
    --     ["value"] = 6,
    -- },
    -- [3] = {
    --     ["number"] = 5,
    --     ["shape"] = 2,
    --     ["value"] = 5,
    -- },
    -- [4] = {
    --     ["number"] = 4,
    --     ["shape"] = 1,
    --     ["value"] = 4,
    -- },
    -- [5] = {
    --     ["number"] = 3,
    --     ["shape"] = 1,
    --     ["value"] = 3,
    -- },

}


local testData         = {
   [1] = {
        ["number"] = 16,
        ["shape"] = 4,
        ["value"] = 16,
        ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 1,
    },
    [2] = {
        ["number"] = 17,
        ["shape"] = 5,
        ["value"] = 17,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 1,
    },
    [3] = {
        ["number"] = 12,
        ["shape"] = 3,
        ["value"] = 12,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [4] = {
        ["number"] = 12,
        ["shape"] = 3,
        ["value"] = 12,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [5] = {
        ["number"] = 12,
        ["shape"] = 3,
        ["value"] = 12,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [6] = {
        ["number"] = 12,
        ["shape"] = 3,
        ["value"] = 12,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [7] = {
        ["number"] = 10,
        ["shape"] = 3,
        ["value"] = 10,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [8] = {
        ["number"] = 10,
        ["shape"] = 3,
        ["value"] = 10,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
    [9] = {
        ["number"] = 10,
        ["shape"] = 3,
        ["value"] = 10,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
     [10] = {
        ["number"] = 9,
        ["shape"] = 3,
        ["value"] = 9,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
     [11] = {
        ["number"] = 9,
        ["shape"] = 3,
        ["value"] = 9,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
     [12] = {
        ["number"] = 9,
        ["shape"] = 3,
        ["value"] = 9,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
    },
     [13] = {
        ["number"] = 9,
        ["shape"] = 3,
        ["value"] = 9,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
     },
     [14] = {
        ["number"] = 7,
        ["shape"] = 3,
        ["value"] = 7,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
     },
     [15] = {
        ["number"] = 7,
        ["shape"] = 3,
        ["value"] = 7,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
     },
     [16] = {
        ["number"] = 7,
        ["shape"] = 3,
        ["value"] = 7,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
     },
     [17] = {
        ["number"] = 7,
        ["shape"] = 3,
        ["value"] = 7,
         ["laiziNumber"] = 0,
        ["laiziType"] = 0,
         ["laizi"] = 0,
     },
    -- [4] = {
    --     ["number"] = 11,
    --     ["shape"] = 0,
    --     ["value"] = 11,
    --      ["laiziNumber"] = 0,
    --     ["laiziType"] = 0,
    --      ["laizi"] = 0,
    -- },
    -- [4] = {
    --     ["number"] = 2,
    --     ["shape"] = 3,
    --     ["value"] = 15,
    -- },
    -- [5] = {
    --     ["number"] = 8,
    --     ["shape"] = 2,
    --     ["value"] = 8,
    -- },
    -- [6] = {
    --     ["number"] = 8,
    --     ["shape"] = 1,
    --     ["value"] = 8,
    -- },
    -- [7] = {
    --     ["number"] = 8,
    --     ["shape"] = 0,
    --     ["value"] = 8,
    -- },
    -- [8] = {
    --     ["number"] = 7,
    --     ["shape"] = 3,
    --     ["value"] = 7,
    -- },
    -- [9] = {
    --     ["number"] = 7,
    --     ["shape"] = 2,
    --     ["value"] = 7,
    -- },
    -- [10] = {
    --     ["number"] = 7,
    --     ["shape"] = 1,
    --     ["value"] = 7,
    -- },
    -- [11] = {
    --     ["number"] = 7,
    --     ["shape"] = 0,
    --     ["value"] = 7,
    -- },
    -- [12] = {
    --     ["number"] = 6,
    --     ["shape"] = 3,
    --     ["value"] = 6,
    -- },
    -- [13] = {
    --     ["number"] = 6,
    --     ["shape"] = 2,
    --     ["value"] = 6,
    -- },
    -- [14] = {
    --     ["number"] = 6,
    --     ["shape"] = 1,
    --     ["value"] = 6,
    -- },
    -- [15] = {
    --     ["number"] = 6,
    --     ["shape"] = 0,
    --     ["value"] = 6,
    -- },
    -- [16] = {
    --     ["number"] = 5,
    --     ["shape"] = 3,
    --     ["value"] = 5,
    -- },
    -- [17] = {
    --     ["number"] = 5,
    --     ["shape"] = 2,
    --     ["value"] = 5,
    -- },
    -- [18] = {
    --     ["number"] = 5,
    --     ["shape"] = 1,
    --     ["value"] = 5,
    -- },
    -- [19] = {
    --     ["number"] = 5,
    --     ["shape"] = 0,
    --     ["value"] = 5,
    -- },
}

local Cards = require(basePath .. "domain/cards");
---
 -- [ctor 默认类的构造方法]
 -- @DateTime 2017-09-20
 -- @param     [description]
 -- @return    [description]
 --
function AglorithmInterface:ctor(...)
  
end

function AglorithmInterface:init()
	if not self.analysisFactory then
	    local analysisFactory = pokercore.new(SuitAnalysisFactory);
		analysisFactory:addSuitAnalyzer(pokercore.new(StraightTypeAnalyzer));
		analysisFactory:addSuitAnalyzer(pokercore.new(SuperBombTypeAnalyzer))
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeTypeAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeStraightTypeAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeTakePairTypeAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeTakePairPlusTypeAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(FourTakePairTypeAnalyzer));
		analysisFactory:addSuitAnalyzer(pokercore.new(PairAnalyzer));
		analysisFactory:addSuitAnalyzer(pokercore.new(SingleAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(FourTakeSingleAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeTakeSingleTypeAnalyzer));
		--analysisFactory:addSuitAnalyzer(pokercore.new(ThreeTakeSinglePlusTypeAnalyzer));
		analysisFactory:addSuitAnalyzer(pokercore.new(BombTypeAnalyzer)); 
		analysisFactory:addSuitAnalyzer(pokercore.new(PairStraightAnalyzer));
		analysisFactory:addSuitAnalyzer(pokercore.new(SoftBombAnalyzer));
	    --analysisFactory:addSuitAnalyzer(pokercore.new(MissileAnalyzer));
	    self.analysisFactory = analysisFactory ;
	end
end


--[[
 -- 单例模式
 -- @DateTime 2017-11-14
 -- @return   [description]
 ]]
AglorithmInterface.getInstance = function()
   if not AglorithmInterface._instance then
   	  AglorithmInterface._instance = pokercore.new(AglorithmInterface) ;
   	  AglorithmInterface._instance:init();
   end
   return AglorithmInterface._instance ;
end

--[[
 -- 获取出牌类型
 -- @DateTime 2017-11-15
 -- @param    outCards [description]
 -- @return    [description]
 ]]
function AglorithmInterface:_getCardsList(outCardType,outCards)
 	local tbCards = {};
	for k, v in ipairs(outCards or {}) do 
		local card = pokercore.new(DdzCard,CardShape.valueOf(v.shape), v.number, v.laizi ==1 ,v.value,v.laiziNumber):revalue();
		table.insert(tbCards, card);
	end
	local cards =  pokercore.new(Cards,tbCards)
    --print("cards->",cards)
    local types = self.analysisFactory:listPossibleTypes(cards:clone(),nil,nil,true);
    --dump(types,"types->");
    if not types or #types == 0 then
    	return  {};
    end
    -- if #types > 1 then
    -- 	
    -- end
    -- if outCardType and outCardType ~= types[1] then
	--     --print("type类型对不上！");
	-- end
    --dump(types,"types")
    local cardsList = {} ;
    if outCardType then
    	table.addAll(cardsList,self.analysisFactory:analysisLaizi(cards,nil,outCardType));
    else
  		for _,curType in pairs(types) do
			table.addAll(cardsList,self.analysisFactory:analysisLaizi(cards:clone(), nil, curType));
    	end
    end
    return cardsList ;
end




function AglorithmInterface:_getCardsListTips(outCardType,outCards)
    --dump(outCards,"outCards->");
 	 --列出所有牌型
 	local types = {} ;
 	if not outCardType then
		table.addAll(types,self.analysisFactory:listAbstractSuitType(false));
 	else
        local insTypesList = {DdzCardTypes.SOFT_BOMB,DdzCardTypes.BOMB,DdzCardTypes.MISSILE,DdzCardTypes.SUPER_BOMB} ;
        for _,v in ipairs(insTypesList) do
            if v.type ~= outCardType.type then
                table.insert(types,v);
            end
        end
        table.insert(types,outCardType)
    end
    local tbCards = {};
	for k, v in ipairs(outCards or {}) do 
		local card = pokercore.new(DdzCard,CardShape.valueOf(v.shape), v.number, v.laizi ==1 ,v.value,v.laiziNumber):revalue();
        --dump(card,"card->");
		table.insert(tbCards, card);
	end
	local cards =  pokercore.new(Cards,tbCards)
    local result = {} ;
    if  not types or #types == 0 then
        --dump(testCards,"找不到对应的牌型");
        --print("找不到对应的牌型");
    else 
       --dump(types,"types->");
        --dump(cards,"cards->");
        --print("cards->",cards)
        for _,type in ipairs(types) do
            --dump(type,"type->");
            local cardsList = self.analysisFactory:listInTypePossibleCards(pokercore.clone(cards),nil,type);
            table.addAll(result,cardsList);
        end
    end
    table.sort(result,function(a,b)
        return a:getResult():compareToSort(b:getResult()) ;
    end);
    -- dump(result,"_getCardsListTips");
    return result ;
end

--[[
 -- 数据转换为前端需要的数据
 -- @DateTime 2017-11-22
 -- @param    cardsList [description]
 -- @param    currentOutcard [description]
 -- @return   result 牌值列表
 -- @return   typesList 类型列表
 ]]
function AglorithmInterface:changeCardsListToCardsDataList(cardsList,currentOutcard)
   local result = {} ;
   local typesList  = {} ;
   for _,cards in ipairs(cardsList) do
   	   local tempData = {} ;
       
   	   local cardList = cards:getCardList() ;
   	   for _,card in ipairs(cardList) do
   	   	  local tempCard = {} ;
   	   	  tempCard.number = card:getNumber() ;
   	   	  tempCard.shape = card.cardShape:getShape();
   	   	  tempCard.value = card:getValue() ;
          tempCard.laizi = card:isLazi() and 1 or 0;     
          tempCard.laiziType = card:getLaiziType();    
          tempCard.laiziNumber = card:getLaiziNumber();  
   	   	  table.insert(tempData,tempCard);
   	   end
      table.insert(result,tempData);
      table.insert(typesList,cards:getType():getType());
   end
   --dump(result,"result");
   return result,typesList ;
end


--[[
 -- 检查当前出牌是否符合规则
 -- @DateTime 2017-11-14
 -- @param    lastOutcard [description]
 -- @param    currentOutcard [description]
 -- @param    laiziCard [description]
 -- @return    [description]
 ]]
function AglorithmInterface:checkOutcardValid(lastOutcardType,lastOutcard,currentOutcard )
	--currentOutcard = testData ;
	--lastOutcard = outData ;
    --如果没有出牌 ;
    if not lastOutcard then
        local currentOutCardsList = self:_getCardsList(nil,currentOutcard);
    	return self:changeCardsListToCardsDataList(currentOutCardsList or {},currentOutcard);
    end

    local lastOutCardsList = self:_getCardsList(nil,lastOutcard);
    if #lastOutCardsList > 1 then
    	--print("出牌有多个牌型!有问题~!");
    end
    --print("outCards",outCards);
    local currentOutCardsList = self:_getCardsList(nil,currentOutcard);

    if not currentOutCardsList or #currentOutCardsList == 0 then
    	--print("该牌型不行");
    	return {} ;
    end
    --dump(self:changeCardsListToCardsDataList(currentOutCardsList),"currentOutCardsList");
    for i = #currentOutCardsList ,1 ,-1 do
    	local cards = currentOutCardsList[i] ;
       -- print("cards",cards);
        if cards:getResult():compareToFlip(lastOutCardsList[1]:getResult())  then --权重小的移除
            table.remove(currentOutCardsList,i);
        elseif self:_checkIsLaiZiShun(cards) then
            table.remove(currentOutCardsList,i);
        end
    end
    --dump(self:changeCardsListToCardsDataList(currentOutCardsList),"currentOutCardsList");
    return self:changeCardsListToCardsDataList(currentOutCardsList,currentOutcard);
end


--[[
 -- 获取出牌的lua cards 对象 只会有一个对象
 -- @DateTime 2017-11-28
 -- @param    outcards [description]
 -- @return    [description]
 ]]
function AglorithmInterface:getOutCards(outcards)
    local lastOutCardsList = self:_getCardsList(nil,outcards);
    if #lastOutCardsList > 1 then
        print("出牌有多个牌型!有问题~!");
    end
    local outCards = lastOutCardsList[1] or {} ;
    return outCards ;
end


--[[
 -- 判断是否是癞子顺
 -- @DateTime 2018-01-02
 -- @return   [description]
 ]]
function AglorithmInterface:_checkIsLaiZiShun(cards)
    local cardList = cards:getCardList();
    local justSingleCard = true ;
    local hasJoker = false ;
    local firstNumber = nil 
    for _,v in ipairs(cardList) do
        if v:isLazi() then
           hasJoker = true ; 
        end
        if firstNumber and v.number ~= firstNumber and not v:isLazi() then
            justSingleCard = false ;
            break ;
        elseif not v:isLazi() then
            firstNumber = v.number;
        end
    end
    local cardsType = cards:getType():getType() ;
    local isFilp = false ;
    if cardsType == DdzCardType.BOMB:getType() or  
    cardsType == DdzCardType.SOFT_BOMB:getType() or 
    cardsType == DdzCardType.SUPER_BOMB:getType()  then  --是炸弹之间的比较
        isFilp = true ;
    end

    if hasJoker and justSingleCard and not isFilp then
        return true ;
    end

    return false ;
end

--[[
 -- 牌型提示算法
 -- @DateTime 2017-11-15
 -- @return   [description]
 ]]
function AglorithmInterface:checkTipsValid(lastOutcardType,lastOutcard,currentOutcard)
	currentOutcard = testData ;
	lastOutcard = outData ;
	--print("checkTipsValid");
    -- Log.d("lastOutcard###->",lastOutcard);
   -- Log.d("currentOutcard###->",currentOutcard);
    if not lastOutcard then
        local currentOutCardsList = self:_getCardsListTips(lastOutcardType,currentOutcard);
    	return self:changeCardsListToCardsDataList(currentOutCardsList or {},currentOutcard);
    end

    local lastOutCardsList = self:_getCardsList(lastOutcardType,lastOutcard);
    if #lastOutCardsList > 1 then
    	print("出牌有多个牌型!有问题~!");
    end
   -- dump(lastOutCardsList,"lastOutCardsList");
    local outCards = lastOutCardsList[1] or {} ;
    local outType = nil ;
    if outCards then
        outType = outCards:getResult():getType();
    end
    --print("outCards",outCards);
    local currentOutCardsList = self:_getCardsListTips(outType,currentOutcard);

    if not currentOutCardsList or #currentOutCardsList == 0 then
    	print("该牌型不行");
    	return {} ;
    end
    --dump(self:changeCardsListToCardsDataList(currentOutCardsList),"currentOutCardsList");
    for i = #currentOutCardsList ,1 ,-1 do
    	local cards = currentOutCardsList[i] ;
        if cards:getResult():compareToFlip(lastOutCardsList[1]:getResult())  then --权重小的移除
        	table.remove(currentOutCardsList,i);
        elseif self:_checkIsLaiZiShun(cards) then
            table.remove(currentOutCardsList,i);
        end
        --判断下是否是单牌加癞子
    end
    ------------测试
    --dump(currentOutCardsList,"result->");
    --dump(self:changeCardsListToCardsDataList(currentOutCardsList),"result->");
    --Log.d("remindList###->",self:changeCardsListToCardsDataList(currentOutCardsList));
    return self:changeCardsListToCardsDataList(currentOutCardsList,currentOutcard);
end
---
 -- [dtor 默认类的销毁方法]
 -- @DateTime 2017-09-20
 -- @param     [description]
 -- @return    [description]
 --
function AglorithmInterface:dtor(...)
  
end

return AglorithmInterface;

